home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d13
/
pctv2n2.arc
/
L1.C
< prev
next >
Wrap
Text File
|
1991-08-11
|
12KB
|
288 lines
/* Split screen VGA animation program. Performs page flipping in the
top portion of the screen while displaying non-page flipped
information in the split screen at the bottom of the screen.
Compiled with Borland C++ 2.0 in C compilation mode. */
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <math.h>
#define SCREEN_SEG 0xA000
#define SCREEN_PIXWIDTH 640 /* in pixels */
#define SCREEN_WIDTH 80 /* in bytes */
#define SPLIT_START_LINE 339
#define SPLIT_LINES 141
#define NONSPLIT_LINES 339
#define SPLIT_START_OFFSET 0
#define PAGE0_START_OFFSET (SPLIT_LINES*SCREEN_WIDTH)
#define PAGE1_START_OFFSET ((SPLIT_LINES+NONSPLIT_LINES)*SCREEN_WIDTH)
#define CRTC_INDEX 0x3D4 /* CRT Controller Index register */
#define CRTC_DATA 0x3D5 /* CRT Controller Data register */
#define OVERFLOW 0x07 /* index of CRTC reg holding bit 8 of the
line the split screen starts after */
#define MAX_SCAN 0x09 /* index of CRTC reg holding bit 9 of the
line the split screen starts after */
#define LINE_COMPARE 0x18 /* index of CRTC reg holding lower 8 bits
of line split screen starts after */
#define NUM_BUMPERS (sizeof(Bumpers)/sizeof(bumper))
#define BOUNCER_COLOR 15
#define BACK_COLOR 1 /* playfield background color */
typedef struct { /* one solid bumper to be bounced off of */
int LeftX,TopY,RightX,BottomY;
int Color;
} bumper;
typedef struct { /* one bit pattern to be used for drawing */
int WidthInBytes;
int Height;
unsigned char *BitPattern;
} image;
typedef struct { /* one bouncing object to move around the screen */
int LeftX,TopY; /* location */
int Width,Height; /* size in pixels */
int DirX,DirY; /* motion vectors */
int CurrentX[2],CurrentY[2]; /* current location in each page */
int Color; /* color in which to be drawn */
image *Rotation0; /* rotations for handling the 8 possible */
image *Rotation1; /* intrabyte start address at which the */
image *Rotation2; /* left edge can be */
image *Rotation3;
image *Rotation4;
image *Rotation5;
image *Rotation6;
image *Rotation7;
} bouncer;
void main(void);
void DrawBumperList(bumper *, int, unsigned int);
void DrawSplitScreen(void);
void EnableSplitScreen(void);
void MoveBouncer(bouncer *, bumper *, int);
extern void DrawRect(int,int,int,int,int,unsigned int,unsigned int);
extern void ShowPage(unsigned int);
extern void DrawImage(int,int,image **,int,unsigned int,unsigned int);
extern void ShowBounceCount(void);
extern void TextUp(char *,int,int,unsigned int,unsigned int);
extern void SetBIOS8x8Font(void);
/* All bumpers in the playfield */
bumper Bumpers[] = {
{0,0,19,339,2}, {0,0,639,19,2}, {620,0,639,339,2},
{0,320,639,339,2}, {60,48,79,67,12}, {60,108,79,127,12},
{60,168,79,187,12}, {60,228,79,247,12}, {120,68,131,131,13},
{120,188,131,271,13}, {240,128,259,147,14}, {240,192,259,211,14},
{208,160,227,179,14}, {272,160,291,179,14}, {228,272,231,319,11},
{192,52,211,55,11}, {302,80,351,99,12}, {320,260,379,267,13},
{380,120,387,267,13}, {420,60,579,63,11}, {428,110,571,113,11},
{420,160,579,163,11}, {428,210,571,213,11}, {420,260,579,263,11} };
/* Image for bouncing object when left edge is aligned with bit 7 */
unsigned char _BouncerRotation0[] = {
0xFF,0x0F,0xF0, 0xFE,0x07,0xF0, 0xFC,0x03,0xF0, 0xFC,0x03,0xF0,
0xFE,0x07,0xF0, 0xFF,0xFF,0xF0, 0xCF,0xFF,0x30, 0x87,0xFE,0x10,
0x07,0x0E,0x00, 0x07,0x0E,0x00, 0x07,0x0E,0x00, 0x07,0x0E,0x00,
0x87,0xFE,0x10, 0xCF,0xFF,0x30, 0xFF,0xFF,0xF0, 0xFE,0x07,0xF0,
0xFC,0x03,0xF0, 0xFC,0x03,0xF0, 0xFE,0x07,0xF0, 0xFF,0x0F,0xF0};
image BouncerRotation0 = {3, 20, _BouncerRotation0};
/* Image for bouncing object when left edge is aligned with bit 3 */
unsigned char _BouncerRotation4[] = {
0x0F,0xF0,0xFF, 0x0F,0xE0,0x7F, 0x0F,0xC0,0x3F, 0x0F,0xC0,0x3F,
0x0F,0xE0,0x7F, 0x0F,0xFF,0xFF, 0x0C,0xFF,0xF3, 0x08,0x7F,0xE1,
0x00,0x70,0xE0, 0x00,0x70,0xE0, 0x00,0x70,0xE0, 0x00,0x70,0xE0,
0x08,0x7F,0xE1, 0x0C,0xFF,0xF3, 0x0F,0xFF,0xFF, 0x0F,0xE0,0x7F,
0x0F,0xC0,0x3F, 0x0F,0xC0,0x3F, 0x0F,0xE0,0x7F, 0x0F,0xF0,0xFF};
image BouncerRotation4 = {3, 20, _BouncerRotation4};
/* Initial settings for bouncing object. Only 2 rotations are needed
because the object moves 4 pixels horizontally at a time */
bouncer Bouncer = {156,60,20,20,4,4,156,156,60,60,BOUNCER_COLOR,
&BouncerRotation0,NULL,NULL,NULL,&BouncerRotation4,NULL,NULL,NULL};
unsigned int PageStartOffsets[2] =
{PAGE0_START_OFFSET,PAGE1_START_OFFSET};
unsigned int BounceCount;
void main() {
int DisplayedPage, NonDisplayedPage, Done, i;
union REGS regset;
regset.x.ax = 0x0012; /* set display to 640x480 16-color mode */
int86(0x10, ®set, ®set);
SetBIOS8x8Font(); /* set the pointer to the BIOS 8x8 font */
EnableSplitScreen(); /* turn on the split screen */
/* Display page 0 above the split screen */
ShowPage(PageStartOffsets[DisplayedPage = 0]);
/* Clear both pages to background and draw bumpers in each page */
for (i=0; i<2; i++) {
DrawRect(0,0,SCREEN_PIXWIDTH-1,NONSPLIT_LINES-1,BACK_COLOR,
PageStartOffsets[i],SCREEN_SEG);
DrawBumperList(Bumpers,NUM_BUMPERS,PageStartOffsets[i]);
}
DrawSplitScreen(); /* draw the static split screen info */
BounceCount = 0;
ShowBounceCount(); /* put up the initial zero count */
/* Draw the bouncing object at its initial location */
DrawImage(Bouncer.LeftX,Bouncer.TopY,&Bouncer.Rotation0,
Bouncer.Color,PageStartOffsets[DisplayedPage],SCREEN_SEG);
/* Move the object, draw it in the nondisplayed page, and flip the
page until Esc is pressed */
Done = 0;
do {
NonDisplayedPage = DisplayedPage ^ 1;
/* Erase at current location in the nondisplayed page */
DrawRect(Bouncer.CurrentX[NonDisplayedPage],
Bouncer.CurrentY[NonDisplayedPage],
Bouncer.CurrentX[NonDisplayedPage]+Bouncer.Width-1,
Bouncer.CurrentY[NonDisplayedPage]+Bouncer.Height-1,
BACK_COLOR,PageStartOffsets[NonDisplayedPage],SCREEN_SEG);
/* Move the bouncer */
MoveBouncer(&Bouncer, Bumpers, NUM_BUMPERS);
/* Draw at the new location in the nondisplayed page */
DrawImage(Bouncer.LeftX,Bouncer.TopY,&Bouncer.Rotation0,
Bouncer.Color,PageStartOffsets[NonDisplayedPage],
SCREEN_SEG);
/* Remember where the bouncer is in the nondisplayed page */
Bouncer.CurrentX[NonDisplayedPage] = Bouncer.LeftX;
Bouncer.CurrentY[NonDisplayedPage] = Bouncer.TopY;
/* Flip to the page we just drew into */
ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]);
/* Respond to any keystroke */
if (kbhit()) {
switch (getch()) {
case 0x1B: /* Esc to end */
Done = 1; break;
case 0: /* branch on the extended code */
switch (getch()) {
case 0x48: /* nudge up */
Bouncer.DirY = -abs(Bouncer.DirY); break;
case 0x4B: /* nudge left */
Bouncer.DirX = -abs(Bouncer.DirX); break;
case 0x4D: /* nudge right */
Bouncer.DirX = abs(Bouncer.DirX); break;
case 0x50: /* nudge down */
Bouncer.DirY = abs(Bouncer.DirY); break;
}
break;
default:
break;
}
}
} while (!Done);
/* Restore text mode and done */
regset.x.ax = 0x0003;
int86(0x10, ®set, ®set);
}
/* Draws the specified list of bumpers into the specified page */
void DrawBumperList(bumper * Bumpers, int NumBumpers,
unsigned int PageStartOffset)
{
int i;
for (i=0; i<NumBumpers; i++,Bumpers++) {
DrawRect(Bumpers->LeftX,Bumpers->TopY,Bumpers->RightX,
Bumpers->BottomY,Bumpers->Color,PageStartOffset,
SCREEN_SEG);
}
}
/* Displays the current bounce count */
void ShowBounceCount() {
char CountASCII[7];
itoa(BounceCount,CountASCII,10); /* convert the count to ASCII */
TextUp(CountASCII,344,64,SPLIT_START_OFFSET,SCREEN_SEG);
}
/* Frames the split screen and fills it with various text */
void DrawSplitScreen() {
DrawRect(0,0,SCREEN_PIXWIDTH-1,SPLIT_LINES-1,0,SPLIT_START_OFFSET,
SCREEN_SEG);
DrawRect(0,1,SCREEN_PIXWIDTH-1,4,15,SPLIT_START_OFFSET,
SCREEN_SEG);
DrawRect(0,SPLIT_LINES-4,SCREEN_PIXWIDTH-1,SPLIT_LINES-1,15,
SPLIT_START_OFFSET,SCREEN_SEG);
DrawRect(0,1,3,SPLIT_LINES-1,15,SPLIT_START_OFFSET,SCREEN_SEG);
DrawRect(SCREEN_PIXWIDTH-4,1,SCREEN_PIXWIDTH-1,SPLIT_LINES-1,15,
SPLIT_START_OFFSET,SCREEN_SEG);
TextUp("This is the split screen area...",8,8,SPLIT_START_OFFSET,
SCREEN_SEG);
TextUp("Bounces: ",272,64,SPLIT_START_OFFSET,SCREEN_SEG);
TextUp("\033: nudge left",520,78,SPLIT_START_OFFSET,SCREEN_SEG);
TextUp("\032: nudge right",520,90,SPLIT_START_OFFSET,SCREEN_SEG);
TextUp("\031: nudge down",520,102,SPLIT_START_OFFSET,SCREEN_SEG);
TextUp("\030: nudge up",520,114,SPLIT_START_OFFSET,SCREEN_SEG);
TextUp("Esc to end",520,126,SPLIT_START_OFFSET,SCREEN_SEG);
}
/* Turn on the split screen at the desired line (minus 1 because the
split screen starts *after* the line specified by the LINE_COMPARE
register) (bit 8 of the split screen start line is stored in the
Overflow register, and bit 9 is in the Maximum Scan Line reg) */
void EnableSplitScreen() {
outp(CRTC_INDEX, LINE_COMPARE);
outp(CRTC_DATA, (SPLIT_START_LINE - 1) & 0xFF);
outp(CRTC_INDEX, OVERFLOW);
outp(CRTC_DATA, (((((SPLIT_START_LINE - 1) & 0x100) >> 8) << 4) |
(inp(CRTC_DATA) & ~0x10)));
outp(CRTC_INDEX, MAX_SCAN);
outp(CRTC_DATA, (((((SPLIT_START_LINE - 1) & 0x200) >> 9) << 6) |
(inp(CRTC_DATA) & ~0x40)));
}
/* Moves the bouncer, bouncing if bumpers are hit */
void MoveBouncer(bouncer *Bouncer, bumper *BumperPtr, int NumBumpers) {
int NewLeftX, NewTopY, NewRightX, NewBottomY, i;
/* Move to new location, bouncing if necessary */
NewLeftX = Bouncer->LeftX + Bouncer->DirX; /* new coords */
NewTopY = Bouncer->TopY + Bouncer->DirY;
NewRightX = NewLeftX + Bouncer->Width - 1;
NewBottomY = NewTopY + Bouncer->Height - 1;
/* Compare the new location to all bumpers, checking for bounce */
for (i=0; i<NumBumpers; i++,BumperPtr++) {
/* If moving puts the bouncer inside this bumper, bounce */
if ( (NewLeftX <= BumperPtr->RightX) &&
(NewRightX >= BumperPtr->LeftX) &&
(NewTopY <= BumperPtr->BottomY) &&
(NewBottomY >= BumperPtr->TopY) ) {
/* The bouncer has tried to move into this bumper; figure
out which edge(s) it crossed, and bounce accordingly */
if (((Bouncer->LeftX > BumperPtr->RightX) &&
(NewLeftX <= BumperPtr->RightX)) ||
(((Bouncer->LeftX + Bouncer->Width - 1) <
BumperPtr->LeftX) &&
(NewRightX >= BumperPtr->LeftX))) {
Bouncer->DirX = -Bouncer->DirX; /* bounce horizontally */
NewLeftX = Bouncer->LeftX + Bouncer->DirX;
}
if (((Bouncer->TopY > BumperPtr->BottomY) &&
(NewTopY <= BumperPtr->BottomY)) ||
(((Bouncer->TopY + Bouncer->Height - 1) <
BumperPtr->TopY) &&
(NewBottomY >= BumperPtr->TopY))) {
Bouncer->DirY = -Bouncer->DirY; /* bounce vertically */
NewTopY = Bouncer->TopY + Bouncer->DirY;
}
/* Update the bounce count display; turn over at 10000 */
if (++BounceCount >= 10000) {
TextUp("0 ",344,64,SPLIT_START_OFFSET,SCREEN_SEG);
BounceCount = 0;
} else {
ShowBounceCount();
}
}
}
Bouncer->LeftX = NewLeftX; /* set the final new coordinates */
Bouncer->TopY = NewTopY;
}